#!/usr/bin/env python3
"""
邮件服务层
包含邮件处理的核心业务逻辑
"""

import time
import json
import imaplib
import email
from datetime import datetime, timedelta
from contextlib import contextmanager
import logging

from models import db, EmailAccount, EmailMessage
from utils.email_helpers import imap_utf7_decode, normalize_folder_name, safe_decode_header
from utils.encryption import email_encryption
from utils.imap_pool import imap_connection_pool
from utils.email_parser import parse_email_body

email_logger = logging.getLogger('email_system')


class FetchingContext:
    """邮件拉取上下文管理器,确保状态正确重置"""
    
    def __init__(self, account):
        self.account = account
        self.acquired = False
        self.start_time = None
    
    def __enter__(self):
        self.start_time = time.time()
        try:
            email_logger.info(f"[邮件拉取] 开始获取拉取锁 - 账号: {self.account.email}")
            
            # 检查是否正在拉取 + 超时保护(15分钟)
            if self.account.is_fetching:
                if self.account.last_fetch_at and \
                   datetime.utcnow() - self.account.last_fetch_at < timedelta(minutes=15):
                    email_logger.warning(f"[邮件拉取] 账号 {self.account.email} 正在拉取中，跳过")
                    return self
                else:
                    # 超时了,强制解锁
                    email_logger.warning(f"[邮件拉取] 检测到超时锁,强制解除: {self.account.email}")
            
            self.account.is_fetching = True
            self.account.last_fetch_at = datetime.utcnow()
            db.session.commit()
            self.acquired = True
            
            email_logger.info(f"[邮件拉取] 成功获取拉取锁 - 账号: {self.account.email}")
            
        except Exception as e:
            email_logger.error(f"[邮件拉取] 获取拉取锁失败: {e}")
            db.session.rollback()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        duration = time.time() - self.start_time if self.start_time else 0
        
        try:
            self.account.is_fetching = False
            db.session.commit()
            
            if exc_type is None:
                email_logger.info(f"[邮件拉取] 拉取完成 - 账号: {self.account.email}, 耗时: {duration:.2f}秒")
            else:
                email_logger.error(f"[邮件拉取] 拉取异常 - 账号: {self.account.email}, 耗时: {duration:.2f}秒, 错误: {exc_val}")
                
        except Exception as e:
            email_logger.error(f"[邮件拉取] 释放拉取锁失败: {e}")
            try:
                db.session.rollback()
                EmailAccount.query.filter_by(id=self.account.id).update({'is_fetching': False})
                db.session.commit()
                email_logger.info(f"[邮件拉取] 强制释放拉取锁成功 - 账号: {self.account.email}")
            except Exception as final_error:
                email_logger.error(f"[邮件拉取] 无法释放拉取锁: {final_error}")


@contextmanager
def imap_connection(account):
    """IMAP连接上下文管理器"""
    mail = None
    start_time = time.time()
    
    try:
        email_logger.info(f"[IMAP连接] 开始连接 - 服务器: {account.imap_server}:{account.imap_port}, SSL: {account.use_ssl}")
        
        password = email_encryption.decrypt_password(account.password)
        
        if account.use_ssl:
            mail = imaplib.IMAP4_SSL(account.imap_server, account.imap_port, timeout=30)
        else:
            mail = imaplib.IMAP4(account.imap_server, account.imap_port, timeout=30)
        
        email_logger.info(f"[IMAP连接] TCP连接成功 - 耗时: {time.time() - start_time:.2f}秒")
        
        login_start = time.time()
        mail.login(account.username, password)
        email_logger.info(f"[IMAP连接] 登录成功 - 用户: {account.username}, 耗时: {time.time() - login_start:.2f}秒")
        
        yield mail
        
    except imaplib.IMAP4.error as e:
        email_logger.error(f"[IMAP连接] IMAP错误: {e}")
        raise
    except Exception as e:
        email_logger.error(f"[IMAP连接] 连接失败: {e}")
        raise
    finally:
        if mail:
            try:
                mail.close()
                email_logger.info(f"[IMAP连接] 连接已关闭")
            except Exception as e:
                email_logger.warning(f"[IMAP连接] 关闭连接失败: {e}")
            try:
                mail.logout()
                email_logger.info(f"[IMAP连接] 已登出")
            except Exception as e:
                email_logger.warning(f"[IMAP连接] 登出失败: {e}")
        
        total_duration = time.time() - start_time
        email_logger.info(f"[IMAP连接] 总耗时: {total_duration:.2f}秒")


class EmailService:
    """邮件服务类 - 统一管理邮件业务逻辑"""
    
    @staticmethod
    def fetch_headers_only_with_callback(mail, email_ids, account, normalized_name, imap_folder_name, batch_callback=None):
        """批量拉取邮件头部信息 - 支持批次回调插入数据库"""
        total_fetched = 0
        start_time = time.time()
        
        # 批量处理,每批30封
        BATCH_SIZE = 30
        total_batches = (len(email_ids) + BATCH_SIZE - 1) // BATCH_SIZE
        
        email_logger.info(f"[批量拉取] 开始拉取邮件头部 - 文件夹: {normalized_name}, 总数: {len(email_ids)}, 批次: {total_batches}")
        
        for i in range(0, len(email_ids), BATCH_SIZE):
            batch_ids = email_ids[i:i + BATCH_SIZE]
            batch_num = i // BATCH_SIZE + 1
            batch_start_time = time.time()
            
            try:
                email_logger.info(f"[批量拉取] 处理批次 {batch_num}/{total_batches} - 邮件数: {len(batch_ids)}")
                
                # 关键优化: 使用逗号分隔的ID列表一次性获取多封邮件
                id_list = b','.join(batch_ids)
                fetch_start_time = time.time()
                status, msg_data_list = mail.fetch(id_list, '(UID FLAGS RFC822.SIZE RFC822.HEADER)')
                fetch_duration = time.time() - fetch_start_time
                
                if status != 'OK' or not msg_data_list:
                    email_logger.error(f"[批量拉取] 批次 {batch_num} FETCH失败 - 状态: {status}")
                    continue
                    
                email_logger.info(f"[批量拉取] 批次 {batch_num} FETCH成功 - 耗时: {fetch_duration:.2f}秒, 返回数据: {len(msg_data_list)}条")
                
                # 解析批量返回的数据
                batch_headers = []
                parsed_count = 0
                
                for j in range(0, len(msg_data_list), 2):  # 每两个元素是一封邮件的数据
                    if j + 1 >= len(msg_data_list):
                        break
                    
                    try:
                        item = msg_data_list[j]
                        
                        if not isinstance(item, tuple) or len(item) < 2:
                            continue
                        
                        header_str = item[0].decode('utf-8')
                        header_content = item[1]
                        
                        # 解析UID
                        uid = None
                        if 'UID' in header_str:
                            uid_match = header_str.split('UID')[1].split()[0]
                            try:
                                uid = int(uid_match)
                            except ValueError:
                                continue
                        
                        # 解析大小
                        size = None
                        if 'RFC822.SIZE' in header_str:
                            size_match = header_str.split('RFC822.SIZE')[1].split()[0]
                            try:
                                size = int(size_match)
                            except ValueError:
                                pass
                        
                        # 解析FLAGS以确定is_read状态
                        is_read = False
                        if 'FLAGS' in header_str:
                            try:
                                flags_part = header_str.split('FLAGS (', 1)[1].split(')', 1)[0]
                                if '\\Seen' in flags_part:
                                    is_read = True
                            except IndexError:
                                is_read = False
                        
                        if not isinstance(header_content, bytes):
                            continue
                        
                        # 解析邮件头部
                        email_message = email.message_from_bytes(header_content)
                        
                        # 获取Message-ID（去重将在批次回调中统一处理）
                        message_id = email_message.get('Message-ID', f"local-{uid or i+j}")
                        
                        # 解析邮件头部信息
                        subject = safe_decode_header(email_message.get('Subject', '无主题'))
                        sender = safe_decode_header(email_message.get('From', ''))
                        recipients = safe_decode_header(email_message.get('To', ''))
                        cc = safe_decode_header(email_message.get('Cc', ''))
                        
                        # 获取邮件接收时间
                        received_at = None
                        try:
                            date_str = email_message.get('Date')
                            if date_str:
                                from email.utils import parsedate_to_datetime
                                parsed_date = parsedate_to_datetime(date_str)
                                if parsed_date:
                                    received_at = parsed_date.astimezone().replace(tzinfo=None)
                        except Exception as e:
                            email_logger.warning(f"[邮件拉取] 解析邮件日期失败: {e}")
                        
                        # 确保received_at不为None
                        if received_at is None:
                            received_at = datetime.utcnow()
                        
                        # 创建邮件记录（仅头部）
                        message_data = {
                            'user_id': account.user_id,
                            'email_account_id': account.id,
                            'message_id': message_id,
                            'imap_uid': uid,
                            'subject': subject,
                            'sender': sender,
                            'recipients': json.dumps([recipients]) if recipients else '[]',
                            'cc': json.dumps([cc]) if cc else '[]',
                            'body_text': '',
                            'body_html': '',
                            'attachments': '[]',
                            'is_read': is_read,
                            'is_full_content': False,
                            'content_size': size,
                            'folder': normalized_name,
                            'imap_folder': imap_folder_name,
                            'received_at': received_at
                        }
                        
                        batch_headers.append(message_data)
                        parsed_count += 1
                        
                        # 记录每封邮件的详细信息
                        email_logger.info(f"[邮件详情] 成功解析邮件 - UID: {uid}, 主题: {subject[:50]}..., 发件人: {sender[:30]}..., 大小: {size}字节")
                        
                    except Exception as e:
                        email_logger.warning(f"[批量拉取] 解析单封邮件失败: {e}")
                        continue
                
                # 如果有回调函数，立即插入数据库
                if batch_headers and batch_callback:
                    try:
                        batch_callback(batch_headers, batch_num, total_batches)
                        total_fetched += len(batch_headers)
                        email_logger.info(f"[批量拉取] 批次 {batch_num} 数据库插入成功 - 数量: {len(batch_headers)}")
                    except Exception as e:
                        email_logger.error(f"[批量拉取] 批次 {batch_num} 数据库插入失败: {e}")
                
                batch_duration = time.time() - batch_start_time
                email_logger.info(f"[批量拉取] 批次 {batch_num} 完成 - 解析: {parsed_count}, 耗时: {batch_duration:.2f}秒")
            
            except Exception as e:
                email_logger.error(f"[批量拉取] 批次 {batch_num} 失败: {e}")
                continue
        
        total_duration = time.time() - start_time
        email_logger.info(f"[批量拉取] 文件夹 {normalized_name} 拉取完成 - 总数: {total_fetched}, 耗时: {total_duration:.2f}秒")
        
        return total_fetched
    
    @staticmethod
    def fetch_headers_only(mail, email_ids, account, normalized_name, imap_folder_name):
        """批量拉取邮件头部信息 - 性能优化版（保持向后兼容）"""
        headers_list = []
        start_time = time.time()
        
        # 批量处理,每批30封
        BATCH_SIZE = 30
        total_batches = (len(email_ids) + BATCH_SIZE - 1) // BATCH_SIZE
        
        email_logger.info(f"[批量拉取] 开始拉取邮件头部 - 文件夹: {normalized_name}, 总数: {len(email_ids)}, 批次: {total_batches}")
        
        for i in range(0, len(email_ids), BATCH_SIZE):
            batch_ids = email_ids[i:i + BATCH_SIZE]
            batch_num = i // BATCH_SIZE + 1
            batch_start_time = time.time()
            
            try:
                email_logger.info(f"[批量拉取] 处理批次 {batch_num}/{total_batches} - 邮件数: {len(batch_ids)}")
                
                # 关键优化: 使用逗号分隔的ID列表一次性获取多封邮件
                id_list = b','.join(batch_ids)
                fetch_start_time = time.time()
                status, msg_data_list = mail.fetch(id_list, '(UID FLAGS RFC822.SIZE RFC822.HEADER)')
                fetch_duration = time.time() - fetch_start_time
                
                if status != 'OK' or not msg_data_list:
                    email_logger.error(f"[批量拉取] 批次 {batch_num} FETCH失败 - 状态: {status}")
                    continue
                
                email_logger.info(f"[批量拉取] 批次 {batch_num} FETCH成功 - 耗时: {fetch_duration:.2f}秒, 返回数据: {len(msg_data_list)}条")
                
                # 解析批量返回的数据
                parsed_count = 0
                skipped_count = 0
                
                for j in range(0, len(msg_data_list), 2):  # 每两个元素是一封邮件的数据
                    if j + 1 >= len(msg_data_list):
                        break
                    
                    try:
                        item = msg_data_list[j]
                        
                        if not isinstance(item, tuple) or len(item) < 2:
                            continue
                        
                        header_str = item[0].decode('utf-8')
                        header_content = item[1]
                        
                        # 解析UID
                        uid = None
                        if 'UID' in header_str:
                            uid_match = header_str.split('UID')[1].split()[0]
                            try:
                                uid = int(uid_match)
                            except ValueError:
                                continue
                        
                        # 解析大小
                        size = None
                        if 'RFC822.SIZE' in header_str:
                            size_match = header_str.split('RFC822.SIZE')[1].split()[0]
                            try:
                                size = int(size_match)
                            except ValueError:
                                pass
                        
                        # 解析FLAGS以确定is_read状态
                        is_read = False
                        if 'FLAGS' in header_str:
                            try:
                                flags_part = header_str.split('FLAGS (', 1)[1].split(')', 1)[0]
                                if '\\Seen' in flags_part:
                                    is_read = True
                            except IndexError:
                                is_read = False
                        
                        if not isinstance(header_content, bytes):
                            continue
                    
                        # 解析邮件头部
                        email_message = email.message_from_bytes(header_content)
                
                        # 检查邮件是否已存在
                        message_id = email_message.get('Message-ID', f"local-{uid or i+j}")
                        existing_message = EmailMessage.query.filter_by(
                            user_id=account.user_id,
                            message_id=message_id
                        ).first()
                
                        if existing_message:
                            skipped_count += 1
                            email_logger.info(f"[邮件详情] 跳过重复邮件 - UID: {uid}, Message-ID: {message_id}")
                            continue
                
                        # 解析邮件头部信息
                        subject = safe_decode_header(email_message.get('Subject', '无主题'))
                        sender = safe_decode_header(email_message.get('From', ''))
                        recipients = safe_decode_header(email_message.get('To', ''))
                        cc = safe_decode_header(email_message.get('Cc', ''))
                
                        # 获取邮件接收时间
                        received_at = None
                        try:
                            date_str = email_message.get('Date')
                            if date_str:
                                from email.utils import parsedate_to_datetime
                                parsed_date = parsedate_to_datetime(date_str)
                                if parsed_date:
                                    received_at = parsed_date.astimezone().replace(tzinfo=None)
                        except Exception as e:
                            email_logger.warning(f"[邮件拉取] 解析邮件日期失败: {e}")
                        
                        # 确保received_at不为None
                        if received_at is None:
                            received_at = datetime.utcnow()
                
                        # 创建邮件记录（仅头部）
                        message_data = {
                            'user_id': account.user_id,
                            'email_account_id': account.id,
                            'message_id': message_id,
                            'imap_uid': uid,
                            'subject': subject,
                            'sender': sender,
                            'recipients': json.dumps([recipients]) if recipients else '[]',
                            'cc': json.dumps([cc]) if cc else '[]',
                            'body_text': '',
                            'body_html': '',
                            'attachments': '[]',
                            'is_read': is_read,
                            'is_full_content': False,
                            'content_size': size,
                            'folder': normalized_name,
                            'imap_folder': imap_folder_name,
                            'received_at': received_at
                        }
                
                        headers_list.append(message_data)
                        parsed_count += 1
                        
                        # 记录每封邮件的详细信息
                        email_logger.info(f"[邮件详情] 成功解析邮件 - UID: {uid}, 主题: {subject[:50]}..., 发件人: {sender[:30]}..., 大小: {size}字节")
                
                    except Exception as e:
                        email_logger.warning(f"[批量拉取] 解析单封邮件失败: {e}")
                        continue
                
                batch_duration = time.time() - batch_start_time
                email_logger.info(f"[批量拉取] 批次 {batch_num} 完成 - 解析: {parsed_count}, 跳过: {skipped_count}, 耗时: {batch_duration:.2f}秒")
            
            except Exception as e:
                email_logger.error(f"[批量拉取] 批次 {batch_num} 失败: {e}")
                continue
        
        total_duration = time.time() - start_time
        email_logger.info(f"[批量拉取] 文件夹 {normalized_name} 拉取完成 - 总数: {len(headers_list)}, 耗时: {total_duration:.2f}秒")
        
        return headers_list
    
    @staticmethod
    def fetch_full_email_body(account_id, message_id):
        """按需拉取单封邮件的完整正文"""
        start_time = time.time()
        try:
            # 查找邮件记录
            message = EmailMessage.query.filter_by(id=message_id).first()
            if not message:
                email_logger.error(f"[加载正文] 邮件不存在 - ID: {message_id}")
                return {'success': False, 'error': '邮件不存在'}
            
            # 检查是否已经加载完整内容
            if message.is_full_content:
                email_logger.info(f"[加载正文] 邮件已加载完整内容 - ID: {message_id}")
                return {'success': True, 'message': message.to_dict()}
            
            # 获取邮箱账号
            account = EmailAccount.query.filter_by(id=account_id).first()
            if not account:
                email_logger.error(f"[加载正文] 邮箱账号不存在 - ID: {account_id}")
                return {'success': False, 'error': '邮箱账号不存在'}
            
            email_logger.info(f"[加载正文] 开始加载邮件正文 - 邮件ID: {message_id}, UID: {message.imap_uid}, 文件夹: {message.folder}")
            
            # 使用连接池获取连接
            with imap_connection_pool.get_connection(account) as mail:
                # 选择文件夹
                select_start_time = time.time()
                # Use imap_folder if available, fallback to folder for backward compatibility
                imap_folder_name = message.imap_folder if message.imap_folder else message.folder
                status, select_data = mail.select(imap_folder_name)
                select_duration = time.time() - select_start_time
                
                if status != 'OK':
                    email_logger.error(f"[加载正文] 无法选择文件夹 {imap_folder_name}: {select_data}")
                    return {'success': False, 'error': f'无法选择文件夹: {imap_folder_name}'}
            
                email_logger.info(f"[加载正文] 文件夹选择成功 - {imap_folder_name}, 耗时: {select_duration:.2f}秒")
            
                # 使用 UID FETCH 获取完整邮件
                msg_data = None
                
                if message.imap_uid:
                    # 使用 mail.uid() 方法来通过UID获取邮件
                    email_logger.info(f"[加载正文] 使用UID获取: {message.imap_uid}")
                    fetch_start_time = time.time()
                    status, msg_data = mail.uid('FETCH', str(message.imap_uid), '(RFC822)')
                    fetch_duration = time.time() - fetch_start_time
                    email_logger.info(f"[加载正文] UID FETCH 状态: {status}, 耗时: {fetch_duration:.2f}秒")
                else:
                    # 如果没有UID，使用message_id搜索
                    email_logger.info(f"[加载正文] 使用Message-ID搜索: {message.message_id}")
                    search_start_time = time.time()
                    status, search_data = mail.search(None, f'HEADER Message-ID "{message.message_id}"')
                    search_duration = time.time() - search_start_time
                    
                    if status != 'OK' or not search_data or not search_data[0]:
                        email_logger.error(f"[加载正文] 搜索邮件失败: {status}")
                        return {'success': False, 'error': '无法找到邮件'}
                    
                    email_ids = search_data[0].split()
                    if not email_ids:
                        email_logger.error(f"[加载正文] 搜索结果为空")
                        return {'success': False, 'error': '无法找到邮件'}
                    
                    # 使用序列号获取
                    fetch_start_time = time.time()
                    status, msg_data = mail.fetch(email_ids[0], '(RFC822)')
                    fetch_duration = time.time() - fetch_start_time
                    email_logger.info(f"[加载正文] FETCH 状态: {status}, 耗时: {fetch_duration:.2f}秒")
            
                # 验证返回数据
                if status != 'OK':
                    email_logger.error(f"[加载正文] FETCH失败，状态: {status}")
                    return {'success': False, 'error': f'FETCH失败: {status}'}
                
                if not msg_data:
                    email_logger.error(f"[加载正文] msg_data为空")
                    return {'success': False, 'error': '邮件数据为空'}
                
                # 安全地提取邮件内容
                email_body = None
                
                email_logger.info(f"[加载正文] msg_data长度: {len(msg_data)}, 第一个元素类型: {type(msg_data[0]) if msg_data else 'None'}")
                
                # IMAP fetch 返回的数据结构: [(b'1 (RFC822 {size}', email_bytes), b')')]
                for item in msg_data:
                    if isinstance(item, tuple) and len(item) >= 2:
                        # item[0] 是头部信息（包含标志和大小）
                        # item[1] 是实际的邮件内容（bytes）
                        if isinstance(item[1], bytes):
                            email_body = item[1]
                            email_logger.info(f"[加载正文] 成功提取邮件内容，大小: {len(email_body)} 字节")
                            break
                
                if not email_body:
                    email_logger.error(f"[加载正文] 无法从返回数据中提取邮件内容")
                    return {'success': False, 'error': '无法解析邮件数据'}
                
                # 使用优化解析模块
                parse_start_time = time.time()
                body_text, body_html, attachments = parse_email_body(email_body)
                parse_duration = time.time() - parse_start_time
                
                email_logger.info(f"[加载正文] 邮件解析完成 - 文本长度: {len(body_text)}, HTML长度: {len(body_html)}, 附件数: {len(attachments)}, 耗时: {parse_duration:.2f}秒")
                
                # 更新邮件记录
                update_start_time = time.time()
                message.body_text = body_text
                message.body_html = body_html
                message.attachments = json.dumps(attachments)
                message.is_full_content = True
                message.updated_at = datetime.utcnow()
                
                db.session.commit()
                
                update_duration = time.time() - update_start_time
                total_duration = time.time() - start_time
                
                email_logger.info(f"[加载正文] 成功更新邮件 {message_id} - 文本长度: {len(body_text)}, HTML长度: {len(body_html)}, 解析耗时: {parse_duration:.2f}秒, 更新耗时: {update_duration:.2f}秒, 总耗时: {total_duration:.2f}秒")
                
                return {'success': True, 'message': message.to_dict()}
            
        except imaplib.IMAP4.error as e:
            db.session.rollback()
            total_duration = time.time() - start_time
            email_logger.error(f"[加载正文] IMAP错误 - 邮件ID: {message_id}, 耗时: {total_duration:.2f}秒, 错误: {e}")
            return {'success': False, 'error': f'IMAP错误: {str(e)}'}
        
        except Exception as e:
            db.session.rollback()
            total_duration = time.time() - start_time
            email_logger.error(f"[加载正文] 异常 - 邮件ID: {message_id}, 耗时: {total_duration:.2f}秒, 错误: {e}")
            import traceback
            traceback.print_exc()
            return {'success': False, 'error': f'加载失败: {str(e)}'}
    
    @staticmethod
    def fetch_emails_for_account(account_id):
        """独立的邮件拉取函数，供调度器使用 - 仅拉取邮件头部"""
        from app import app
        
        # 在后台线程中需要创建应用上下文
        with app.app_context():
            try:
                account = EmailAccount.query.filter_by(id=account_id).first()
                
                if not account:
                    email_logger.error(f"[邮件拉取] 邮箱配置不存在 - ID: {account_id}")
                    return {'success': False, 'error': '邮箱配置不存在'}
                
                email_logger.info(f"[邮件拉取] 开始邮件拉取任务 - 账号: {account.email}")
                
                # 使用上下文管理器确保状态重置
                with FetchingContext(account) as ctx:
                    if not ctx.acquired:
                        email_logger.error(f"[邮件拉取] 无法获取拉取锁 - 账号: {account.email}")
                        return {'success': False, 'error': '无法获取拉取锁'}
                    
                    try:
                        # 使用连接池获取连接
                        with imap_connection_pool.get_connection(account) as mail:
                            email_logger.info(f"[邮件拉取] IMAP连接成功，开始获取文件夹列表")
            
                            # 获取所有文件夹
                            list_start_time = time.time()
                            status, folders = mail.list()
                            list_duration = time.time() - list_start_time
                            
                            folder_map = {}  # 存储原始IMAP名称和显示名称的映射
                            if status == 'OK':
                                email_logger.info(f"[邮件拉取] 获取文件夹列表成功 - 耗时: {list_duration:.2f}秒, 数量: {len(folders)}")
                                
                                for folder in folders:
                                    folder_str = folder.decode('utf-8')
                                    # 解析文件夹名称，处理IMAP编码
                                    try:
                                        # 尝试解析IMAP文件夹格式
                                        parts = folder_str.split('"')
                                        if len(parts) >= 3:
                                            imap_folder_name = parts[-2]
                                        else:
                                            imap_folder_name = folder_str.split()[-1]
                                        
                                        # 使用UTF-7解码得到显示名称
                                        display_name = imap_utf7_decode(imap_folder_name)
                                        folder_map[imap_folder_name] = display_name
                                    except Exception as e:
                                        email_logger.warning(f"[邮件拉取] 解析文件夹名称失败: {folder_str}, 错误: {e}")
                                        continue
                            else:
                                email_logger.warning(f"[邮件拉取] 获取文件夹列表失败 - 状态: {status}")
            
                            # 如果没有获取到文件夹，使用默认的文件夹列表
                            if not folder_map:
                                folder_map = {
                                    'INBOX': 'inbox',
                                    'Sent': 'sent', 
                                    'Drafts': 'drafts',
                                    'Trash': 'trash',
                                    'Spam': 'spam'
                                }
                                email_logger.info(f"[邮件拉取] 使用默认文件夹列表")
            
                            # 确保包含用户指定的文件夹
                            required_folders = ['Reuters', 'datasci']
                            for folder in required_folders:
                                if folder not in folder_map.values():
                                    # 查找对应的IMAP名称
                                    for imap_name, display_name in folder_map.items():
                                        if display_name == folder:
                                            break
                                    else:
                                        # 如果没有找到，添加一个映射
                                        folder_map[folder] = folder
            
                            email_logger.info(f"[邮件拉取] 发现文件夹: {list(folder_map.values())}")
            
                            fetched_count = 0
            
                            # 检查是否首次拉取
                            if account.is_first_fetch:
                                # 首次拉取：全量拉取所有文件夹的邮件头
                                email_logger.info(f"[首次全量拉取] 账号: {account.email}")
                                
                                for imap_name, display_name in folder_map.items():
                                    folder_start_time = time.time()
                                    try:
                                        email_logger.info(f"[邮件拉取] 开始处理文件夹: {display_name} ({imap_name})")
                                        
                                        # 选择文件夹
                                        select_start_time = time.time()
                                        status, count = mail.select(imap_name)
                                        select_duration = time.time() - select_start_time
                                        
                                        if status != 'OK':
                                            email_logger.error(f"[邮件拉取] 无法选择文件夹 {imap_name} ({display_name}): {count}")
                                            continue
                    
                                        total_emails_in_folder = int(count[0].decode())
                                        email_logger.info(f"[文件夹] 选择成功 - {display_name}, 总邮件数: {total_emails_in_folder}, 耗时: {select_duration:.2f}秒")
                                        
                                        # 全量拉取该文件夹的所有邮件头
                                        search_start_time = time.time()
                                        status, messages = mail.search(None, 'ALL')
                                        search_duration = time.time() - search_start_time
                                        
                                        if status == 'OK' and messages[0]:
                                            email_ids = messages[0].split()
                                            email_logger.info(f"[首次全量拉取] 文件夹 {display_name} 发现 {len(email_ids)} 封邮件 - 耗时: {search_duration:.2f}秒")
                                            
                                            # 使用辅助函数标准化文件夹名称
                                            normalized_name = normalize_folder_name(display_name)
                                            
                                            # 定义批次插入回调函数
                                            def batch_insert_callback(batch_headers, batch_num, total_batches):
                                                """批次插入回调函数 - 处理重复邮件"""
                                                batch_insert_start_time = time.time()
                                                
                                                try:
                                                    # 先检查哪些邮件已存在（数据库中），并去除批次内部重复
                                                    existing_messages = set()
                                                    seen_in_batch = set()
                                                    batch_duplicates = 0
                                                    
                                                    for header in batch_headers:
                                                        message_id = header['message_id']
                                                        
                                                        # 检查批次内部是否重复
                                                        if message_id in seen_in_batch:
                                                            batch_duplicates += 1
                                                            existing_messages.add(message_id)
                                                            continue
                                                        seen_in_batch.add(message_id)
                                                        
                                                        # 检查数据库中是否已存在
                                                        existing = EmailMessage.query.filter_by(
                                                            user_id=header['user_id'],
                                                            message_id=message_id
                                                        ).first()
                                                        if existing:
                                                            existing_messages.add(message_id)
                                                    
                                                    # 过滤掉已存在的邮件
                                                    new_headers = [h for h in batch_headers if h['message_id'] not in existing_messages]
                                                    
                                                    if new_headers:
                                                        db.session.bulk_insert_mappings(EmailMessage, new_headers)
                                                        db.session.commit()
                                                        
                                                        batch_insert_duration = time.time() - batch_insert_start_time
                                                        email_logger.info(f"[首次全量拉取] 文件夹 {display_name} 批次 {batch_num}/{total_batches} 插入成功 - 新增: {len(new_headers)}, 跳过重复: {len(existing_messages)}(批次内:{batch_duplicates}), 耗时: {batch_insert_duration:.2f}秒")
                                                    else:
                                                        batch_insert_duration = time.time() - batch_insert_start_time
                                                        email_logger.info(f"[首次全量拉取] 文件夹 {display_name} 批次 {batch_num}/{total_batches} 全部为重复邮件 - 跳过: {len(batch_headers)}, 耗时: {batch_insert_duration:.2f}秒")
                                                    
                                                except Exception as e:
                                                    db.session.rollback()
                                                    batch_insert_duration = time.time() - batch_insert_start_time
                                                    email_logger.error(f"[首次全量拉取] 文件夹 {display_name} 批次 {batch_num}/{total_batches} 插入失败: {e}, 耗时: {batch_insert_duration:.2f}秒")
                                                    # 不抛出异常，继续处理下一批次
                                            
                                            # 使用新的批次插入函数
                                            folder_fetched_count = EmailService.fetch_headers_only_with_callback(
                                                mail, email_ids, account, normalized_name, imap_name, batch_insert_callback
                                            )
                                            
                                            if folder_fetched_count > 0:
                                                fetched_count += folder_fetched_count
                                                email_logger.info(f"[首次全量拉取] 文件夹 {display_name} 拉取完成 - 总数: {folder_fetched_count}")
                                            else:
                                                email_logger.info(f"[首次全量拉取] 文件夹 {display_name} 没有有效邮件头")
                                        else:
                                            email_logger.info(f"[首次全量拉取] 文件夹 {display_name} 没有邮件")
                                        
                                        folder_duration = time.time() - folder_start_time
                                        email_logger.info(f"[首次全量拉取] 文件夹 {display_name} 处理完成 - 耗时: {folder_duration:.2f}秒")
                                        
                                    except Exception as e:
                                        folder_duration = time.time() - folder_start_time
                                        email_logger.error(f"[邮件拉取] 文件夹 {display_name} 处理失败 - 耗时: {folder_duration:.2f}秒, 错误: {e}")
                                        continue
                                
                                # 首次拉取完成后，标记为非首次
                                account.is_first_fetch = False
                                db.session.commit()
                                email_logger.info(f"[首次全量拉取] 完成首次全量拉取 - 账号: {account.email}, 总邮件数: {fetched_count}")
                                
                            else:
                                # 增量拉取：基于 last_fetch_at 时间点拉取
                                email_logger.info(f"[增量拉取] 账号: {account.email}")
                                
                                if account.last_fetch_at:
                                    # 计算时间差，拉取该时间点之后的邮件
                                    since_date = account.last_fetch_at - timedelta(hours=1)  # 留1小时缓冲
                                    date_str = since_date.strftime('%d-%b-%Y')
                                    email_logger.info(f"[增量拉取] 基于时间点拉取 - 时间: {since_date}, 日期字符串: {date_str}")
                                else:
                                    # 如果没有last_fetch_at，拉取最近7天的邮件
                                    since_date = datetime.utcnow() - timedelta(days=7)
                                    date_str = since_date.strftime('%d-%b-%Y')
                                    email_logger.info(f"[增量拉取] 首次增量拉取 - 拉取最近7天邮件，日期: {date_str}")
                                
                                for imap_name, display_name in folder_map.items():
                                    folder_start_time = time.time()
                                    try:
                                        email_logger.info(f"[邮件拉取] 开始处理文件夹: {display_name} ({imap_name})")
                                        
                                        # 选择文件夹
                                        select_start_time = time.time()
                                        status, count = mail.select(imap_name)
                                        select_duration = time.time() - select_start_time
                                        
                                        if status != 'OK':
                                            email_logger.error(f"[邮件拉取] 无法选择文件夹 {imap_name} ({display_name}): {count}")
                                            continue
                    
                                        total_emails_in_folder = int(count[0].decode())
                                        email_logger.info(f"[文件夹] 选择成功 - {display_name}, 总邮件数: {total_emails_in_folder}, 耗时: {select_duration:.2f}秒")
                                        
                                        # 增量拉取：基于时间点拉取
                                        search_start_time = time.time()
                                        status, messages = mail.search(None, f'SINCE {date_str}')
                                        search_duration = time.time() - search_start_time
                                        
                                        if status == 'OK' and messages[0]:
                                            email_ids = messages[0].split()
                                            email_logger.info(f"[增量拉取] 文件夹 {display_name} 发现 {len(email_ids)} 封新邮件 - 耗时: {search_duration:.2f}秒")
                                            
                                            # 使用辅助函数标准化文件夹名称
                                            normalized_name = normalize_folder_name(display_name)
                                            
                                            # 定义批次插入回调函数
                                            def batch_insert_callback(batch_headers, batch_num, total_batches):
                                                """批次插入回调函数 - 处理重复邮件"""
                                                batch_insert_start_time = time.time()
                                                
                                                try:
                                                    # 先检查哪些邮件已存在（数据库中），并去除批次内部重复
                                                    existing_messages = set()
                                                    seen_in_batch = set()
                                                    batch_duplicates = 0
                                                    
                                                    for header in batch_headers:
                                                        message_id = header['message_id']
                                                        
                                                        # 检查批次内部是否重复
                                                        if message_id in seen_in_batch:
                                                            batch_duplicates += 1
                                                            existing_messages.add(message_id)
                                                            continue
                                                        seen_in_batch.add(message_id)
                                                        
                                                        # 检查数据库中是否已存在
                                                        existing_message = EmailMessage.query.filter_by(
                                                            user_id=header['user_id'],
                                                            message_id=message_id
                                                        ).first()
                                                        if existing_message:
                                                            existing_messages.add(message_id)
                                                    
                                                    # 过滤掉已存在的邮件
                                                    new_headers = [h for h in batch_headers if h['message_id'] not in existing_messages]
                                                    
                                                    if new_headers:
                                                        db.session.bulk_insert_mappings(EmailMessage, new_headers)
                                                        db.session.commit()
                                                        
                                                        batch_insert_duration = time.time() - batch_insert_start_time
                                                        email_logger.info(f"[增量拉取] 文件夹 {display_name} 批次 {batch_num}/{total_batches} 插入成功 - 新增: {len(new_headers)}, 跳过重复: {len(existing_messages)}(批次内:{batch_duplicates}), 耗时: {batch_insert_duration:.2f}秒")
                                                    else:
                                                        batch_insert_duration = time.time() - batch_insert_start_time
                                                        email_logger.info(f"[增量拉取] 文件夹 {display_name} 批次 {batch_num}/{total_batches} 全部为重复邮件 - 跳过: {len(batch_headers)}, 耗时: {batch_insert_duration:.2f}秒")
                    
                                                except Exception as e:
                                                    db.session.rollback()
                                                    batch_insert_duration = time.time() - batch_insert_start_time
                                                    email_logger.error(f"[增量拉取] 文件夹 {display_name} 批次 {batch_num}/{total_batches} 插入失败: {e}, 耗时: {batch_insert_duration:.2f}秒")
                                                    # 不抛出异常，继续处理下一批次
                                            
                                            # 使用新的批次插入函数
                                            folder_fetched_count = EmailService.fetch_headers_only_with_callback(
                                                mail, email_ids, account, normalized_name, imap_name, batch_insert_callback
                                            )
                                            
                                            if folder_fetched_count > 0:
                                                fetched_count += folder_fetched_count
                                                email_logger.info(f"[增量拉取] 文件夹 {display_name} 拉取完成 - 总数: {folder_fetched_count}")
                                            else:
                                                email_logger.info(f"[增量拉取] 文件夹 {display_name} 没有有效邮件头")
                                        else:
                                            email_logger.info(f"[增量拉取] 文件夹 {display_name} 没有新邮件")
                                        
                                        folder_duration = time.time() - folder_start_time
                                        email_logger.info(f"[增量拉取] 文件夹 {display_name} 处理完成 - 耗时: {folder_duration:.2f}秒")
                                        
                                    except Exception as e:
                                        folder_duration = time.time() - folder_start_time
                                        email_logger.error(f"[邮件拉取] 文件夹 {display_name} 处理失败 - 耗时: {folder_duration:.2f}秒, 错误: {e}")
                                        continue
            
                            # 更新最后拉取时间
                            account.last_fetch_at = datetime.utcnow()
                            db.session.commit()
            
                            email_logger.info(f"[邮件拉取] 账号 {account.email} 拉取完成，共 {fetched_count} 封邮件")
            
                            return {
                                'success': True,
                                'message': f'成功拉取 {fetched_count} 封邮件头部',
                                'fetched_count': fetched_count
                            }
            
                    except imaplib.IMAP4.error as e:
                        error_msg = str(e).lower()
                        email_logger.error(f"[邮件拉取] IMAP错误 - 账号: {account.email}, 错误: {e}")
                        
                        if 'authentication' in error_msg or 'login' in error_msg:
                            return {
                                'success': False, 
                                'error': '认证失败,请检查用户名和密码/授权码',
                                'error_code': 'AUTH_FAILED'
                            }
                        elif 'connection' in error_msg or 'timeout' in error_msg:
                            return {
                                'success': False,
                                'error': '连接服务器失败,请检查网络或服务器地址',
                                'error_code': 'CONNECTION_FAILED'
                            }
                        else:
                            return {
                                'success': False,
                                'error': f'IMAP错误: {str(e)}',
                                'error_code': 'IMAP_ERROR'
                            }
            
                    except Exception as e:
                        email_logger.error(f"[邮件拉取] 未知错误 - 账号: {account.email}, 错误: {e}")
                        import traceback
                        traceback.print_exc()
                        return {
                            'success': False,
                            'error': f'未知错误: {str(e)}',
                            'error_code': 'UNKNOWN_ERROR'
                        }
            
            except Exception as e:
                email_logger.error(f"[邮件拉取] 应用上下文错误: {e}")
                return {
                    'success': False,
                    'error': f'应用上下文错误: {str(e)}',
                    'error_code': 'CONTEXT_ERROR'
                }

